#include "Logic_interface.h"

const int Logic_interface::K_SUCCESS(0);

const int Logic_interface::K_ERROR_NO_DATA_AVAILABLE(1);

const int Logic_interface::K_INVALID_REQUEST(2);

const int Logic_interface::K_ERROR_SERVER_DISCONNECT(3);

Logic_interface::Logic_interface(void) {}

Logic_interface::~Logic_interface(void) {}

int Logic_interface::get_code_error_no_data_available() {
	return K_ERROR_NO_DATA_AVAILABLE;
}

int Logic_interface::get_code_error_server_disconnect() {
	return K_ERROR_SERVER_DISCONNECT;
}

int Logic_interface::get_code_invalid_request() {
	return K_INVALID_REQUEST;
}

int Logic_interface::get_code_success() {
	return K_SUCCESS;
}

int Logic_interface::get_error(int error_code, std::string received_message) {
	if(error_code == Local_connection::get_code_error_no_data_received()) {
		return Logic_interface::get_code_error_no_data_available();
	}

	if(error_code == Local_connection::get_code_error_server_disconnect()) {
		return Logic_interface::get_code_error_server_disconnect();
	}

	if(error_code == Local_connection::get_code_success()) {
		if(received_message == "invalid.\r\n")
			return Logic_interface::get_code_invalid_request();
		else
			return Logic_interface::get_code_success();
			
	}
}

bool Logic_interface::connect_to_logic_module() {
	return m_connection.create_connection(60001);
}

std::string board_transform(std::string board) {
	for(int i = 0; i < board.size(); ++i) {
		switch (board[i]) {
		case '0':
			board[i] = 'b';
			break;

		case '1':
		case '2':
			board.insert(i, std::string("p"));
			++i;
			break;
		}
	}

	return board;
}

int Logic_interface::request_ai_move( std::string board, int player, int difficulty) {
	std::stringstream sstr;

	sstr << "ai_move(" << board_transform(board) << ',' << (player == 1 ? "p1" : "p2") << ',' << difficulty << ").\n";

	std::cout << sstr.str();
	//sstr << '[' << board << ',' << player << ',' << '[' << coords.x << ',' << coords.y << ']' << ']' << '\n';

	int error_code;
	m_connection.send_message(sstr.str(), error_code);

	return get_error(error_code);
}

int Logic_interface::request_new_game() {
	int error_code;
	m_connection.send_message("new_game.", error_code);

	return get_error(error_code);
}

int Logic_interface::request_board_width() {
	int error_code;
	m_connection.send_message("board_width.", error_code);

	return get_error(error_code);
}

int Logic_interface::request_move_validation( std::string board, int player, Vector2D origin, Vector2D final ) {
	std::stringstream sstr;

	sstr << "valid_move(" << "[[" << origin.x << ',' << origin.y << "],[" << final.x << ',' << final.y << "]]," << board_transform(board) << ',' << (player == 1 ? "p1" : "p2") << ").";

	//sstr << '[' << board << ',' << player << ',' << '[' << coords.x << ',' << coords.y << ']' << ']' << '\n';

	int error_code;
	m_connection.send_message(sstr.str(), error_code);

	return get_error(error_code);
}

int Logic_interface::request_winner_verification( std::string board, int player ) {
	std::stringstream sstr;

	sstr << "winner(" << board_transform(board) << ',' << (player == 1 ? "p1" : "p2") << ").";

	//sstr << '[' << board << ',' << player << ',' << '[' << coords.x << ',' << coords.y << ']' << ']' << '\n';

	int error_code;
	m_connection.send_message(sstr.str(), error_code);

	return get_error(error_code);
}

int Logic_interface::request_possible_moves( std::string board, int player, Vector2D position ) {
	std::stringstream sstr;

	sstr << "possible_moves(" << board_transform(board) << ',' << (player == 1 ? "p1" : "p2") << ',' << '[' << position.x << ',' << position.y << "]).";

	//sstr << '[' << board << ',' << player << ',' << '[' << coords.x << ',' << coords.y << ']' << ']' << '\n';

	int error_code;
	m_connection.send_message(sstr.str(), error_code);

	return get_error(error_code);
}

int Logic_interface::parse_ai_move( Vector2D &origin, Vector2D &final ) {
	int error_code;
	std::string message = m_connection.receive_message(false, error_code);

	if(error_code != Local_connection::get_code_success()) {
		return get_error(error_code, message);
	}
	
	sscanf(message.c_str(), "ok([[%d,%d],[%d,%d]])", &origin.x, &origin.y, &final.x, &final.y);

	return get_error(error_code);
}

int Logic_interface::parse_new_game( std::string &board, int &player ) {
	int error_code;
	std::string message = m_connection.receive_message(false, error_code);

	if(error_code != Local_connection::get_code_success()) {
		return get_error(error_code, message);
	}

	board = message.substr(message.find('['), message.rfind(']') - message.find('[') + 1);

	for(int i = 0; i < board.size(); ++i) {
		if(board[i] == '[' || board[i] == ']' || board[i] == ',' || board[i] == 'p')
			board[i] = ' ';
		if(board[i] == 'b')
			board[i] = '0';
	}
	player = 1;
	
	return get_error(error_code);
}

int Logic_interface::parse_move_validation( bool &valid ) {
	int error_code;
	std::string message = m_connection.receive_message(false, error_code);

	if(error_code != Local_connection::get_code_success()) {
		valid = false;
		return get_error(error_code, message);
	}

	valid = true;

	return get_error(error_code);
}

int Logic_interface::parse_winner_verification( bool &won ) {
	int error_code;
	std::string message = m_connection.receive_message(false, error_code);

	if(get_error(error_code, message) != Local_connection::get_code_success()) {
		won = false;
		return get_error(error_code, message);
	}

	won = true;

	return get_error(error_code);
}

int Logic_interface::parse_possible_moves( std::vector<Vector2D> &moves ) {
	int error_code;
	std::string message = m_connection.receive_message(false, error_code);

	if(get_error(error_code, message) != Local_connection::get_code_success()) {
		return get_error(error_code, message);
	}

	std::string moveslist = message.substr(message.find('['), message.rfind(']') - message.find('[') + 1);

	if(moveslist.size() == 2)
		return Logic_interface::get_code_invalid_request();

	for(int i = 0; i < moveslist.size(); ++i) {
		if(moveslist[i] == '[' || moveslist[i] == ']' || moveslist[i] == ',')
			moveslist[i] = ' ';
	}

	std::stringstream sstr;
	sstr << moveslist;

	int tempx, tempy;
	while(sstr >> tempx && sstr >> tempy)
		moves.push_back(Vector2D(tempx, tempy));

	return get_error(error_code);
}
